package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import cn.hutool.core.util.StrUtil;
import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.feign.service.UserFeignService;
import com.alibaba.algo.cooperation.feign.vo.req.SelectUserInfoReqVO;
import com.alibaba.algo.cooperation.feign.vo.res.RpcUserInfoVO;
import com.alibaba.algo.cooperation.feign.vo.res.UserOrgResVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.ProcessInstanceStatusEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.TaskLinkStatusEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.FlowCatalogueService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserGroupService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserPositionService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.BeanCopierUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpFlowRecordsQueryDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpGetTaskDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowExecutionQueryLink;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.app.FlowApp;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.HttpFlowRecordsQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.HttpTaskQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.TaskTraceQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.HttpFlowNodeRecordsQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.statistics.CataloguePageable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.statistics.TaskStatisticsQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.TaskCandidateQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowTenantSimpleInfoVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.GroupInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.OrgInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.PositionInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.RoleInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.UserInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowAppRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskTraceRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.UserRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowTaskTrace;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowTaskTraceExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowExecutionQueryDAO;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowTaskTraceDAO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.common.impl.cfg.IdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lilh
 * @date 2019-07-29 14:50
 */
@Service
@Slf4j
public class FlowTaskTraceRepositoryImpl implements FlowTaskTraceRepository {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private FlowTaskTraceDAO flowTaskTraceDAO;

    @Autowired
    private FlowExecutionQueryDAO flowExecutionQueryDAO;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private FlowCatalogueService catalogueService;

    @Autowired
    private FlowAppRepository flowAppRepository;

    @Autowired
    private UserFeignService userFeignService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserGroupService userGroupService;

    @Autowired
    private UserPositionService userPositionService;

    @Autowired
    private UserService userService;

    @Override
    public int insertTaskTrace(FlowTaskTraceVo flowTaskTraceVo) {
        flowTaskTraceVo.setId(idGenerator.getNextId());
        FlowTaskTrace entity = new FlowTaskTrace();
        BeanUtils.copyProperties(flowTaskTraceVo, entity);
        return flowTaskTraceDAO.insertSelective(entity);
    }

    @Override
    public List<FlowTaskTraceVo> listByProcessInstanceId(String processInstanceId) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId);
        query.setOrderByClause(" create_time ASC");
        return listByExample(query).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public FlowTaskTraceVo taskByTaskId(String taskId) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        query.createCriteria().andTaskIdEqualTo(taskId);
        List<FlowTaskTrace> flowTaskTraces = listByExample(query);
        if (flowTaskTraces.size() > 0) {
            return convert(flowTaskTraces.get(0));
        } else {
            return new FlowTaskTraceVo();
        }
    }

    @Override
    public List<FlowTaskTraceVo> listTask(TaskStatisticsQueryVo taskStatisticsQueryVo) {

        List<FlowTaskTrace> flowTaskTraces = listTaskByExample(taskStatisticsQueryVo);

        return getPageableFlowTaskTraceVos(flowTaskTraces);
    }

    private void fillTenantQueryParams(CataloguePageable tenantParams, FlowTaskTraceExample.Criteria criteria) {
        if (Objects.nonNull(tenantParams.getTenantId())) {
            criteria.andTenantIdEqualTo(tenantParams.getTenantId());
        }

        if (CollectionUtils.isNotEmpty(tenantParams.getTenantIds())) {
            criteria.andTenantIdIn(tenantParams.getTenantIds());
        }

        if (Objects.nonNull(tenantParams.getAppId())) {
            criteria.andAppIdEqualTo(tenantParams.getAppId());
        }

        if (Objects.nonNull(tenantParams.getBusiId())) {
            criteria.andBusiIdEqualTo(tenantParams.getBusiId());
        }
    }

    private List<FlowTaskTraceVo> getPageableFlowTaskTraceVos(List<FlowTaskTrace> flowTaskTraces) {
        PageInfo<FlowTaskTrace> pageInfo = new PageInfo<>(flowTaskTraces);
        Page<FlowTaskTraceVo> result = null;
        try {
            result = new Page<>();
            result.setPageNum(pageInfo.getPageNum()).setPageSize(pageInfo.getPageSize()).addAll(convert(flowTaskTraces));
            result.setTotal(pageInfo.getTotal());
            return result;
        } finally {
            if (Objects.nonNull(result)) {
                result.close();
            }
        }
    }

    private List<FlowTaskTraceVo> getPageableFlowTaskTraceVosForTaskList(List<FlowTaskTrace> flowTaskTraces) {
        PageInfo<FlowTaskTrace> pageInfo = new PageInfo<>(flowTaskTraces);
        Page<FlowTaskTraceVo> result = null;
        try {
            result = new Page<>();
            result.setPageNum(pageInfo.getPageNum()).setPageSize(pageInfo.getPageSize()).addAll(queryOperatorForTaskList(flowTaskTraces));
            result.setTotal(pageInfo.getTotal());
            return result;
        } finally {
            if (Objects.nonNull(result)) {
                result.close();
            }
        }
    }

    //根据taskId添加操作人
    private List<FlowTaskTraceVo> queryOperatorForTaskList(List<FlowTaskTrace> flowTaskTraces) {
        List<FlowTaskTraceVo> temp = convert(flowTaskTraces);
        if (temp.size() == 0) {
            return temp;
        }
        temp.forEach(it -> {
            List<FlowExecutionQueryLink> list = flowExecutionQueryDAO.queryIdentityLinkByTaskId(it.getTaskId());
            log.info("taskId:{},----list--:{}", it.getTaskId(), list);
            list.removeAll(Collections.singleton(null));
            if (Objects.isNull(list) || list.size() == 0) {
                return;
            }
            HashMap<String, HashMap<String, String>> map = new HashMap<>();
            //一个节点在配置处理人的时候，有可能既配置角色 又配置组织 或者岗位  或者人员
            HashMap<String, String> mapUser = new HashMap<>();//存储人员信息
            if (StringUtils.isNotBlank(it.getOperator()) && StringUtils.isNotBlank(it.getOperatorCode())) {
                mapUser.put(it.getOperatorCode(), it.getOperator());
            }
            HashMap<String, String> mapOrg = new HashMap<>(); //存储组织信息
            HashMap<String, String> mapRole = new HashMap<>(); //存储角色信息
            HashMap<String, String> mapPosition = new HashMap<>(); //存储岗位信息
            for (int i = 0; i < list.size(); i++) {
                FlowExecutionQueryLink flowExecutionQueryLink = list.get(i);
                log.info("*****{}***", flowExecutionQueryLink);
                final List<String> test = Arrays.asList("STA", "participant", "starter", "candidate");
                if (test.contains(flowExecutionQueryLink.getType()) && flowExecutionQueryLink.getUserId() != null && isNumString(flowExecutionQueryLink.getUserId())) {
                    User user = userService.getFullUserInfo(flowExecutionQueryLink.getUserId());   //userId必须都是数字  否则会报异常
                    log.info("****userId****:{}, user:{}", flowExecutionQueryLink.getUserId(), user);
                    if (user != null) {
                        if (!mapUser.containsKey(user.getUserId())) {
                            mapUser.put(user.getUserCode(), user.getUserName());
                        }
                    }
                    continue;
                }
                if ("ORG".equals(flowExecutionQueryLink.getType())) {
                    if (flowExecutionQueryLink.getGroupId() != null && flowExecutionQueryLink.getGroupId() != "") {
                        String orgName = userRepository.getOrgNameById(flowExecutionQueryLink.getGroupId());
                        mapOrg.put(flowExecutionQueryLink.getGroupId(), orgName);
                        //operator.append(userRepository.getOrgNameById(flowExecutionQueryLink.getGroupId())+";");
                    }
                    continue;
                }
                if ("ROL".equals(flowExecutionQueryLink.getType())) {
                    if (flowExecutionQueryLink.getGroupId() != null && flowExecutionQueryLink.getGroupId() != "") {
                        String roleName = userRepository.getRoleNameById(flowExecutionQueryLink.getGroupId());
                        mapRole.put(flowExecutionQueryLink.getGroupId(), roleName);
                    }
                    continue;
                }
                if ("POSITION".equals(flowExecutionQueryLink.getType())) {
                    if (flowExecutionQueryLink.getGroupId() != null && flowExecutionQueryLink.getGroupId() != "") {
                        String positionName = userRepository.getPositionDetailById(flowExecutionQueryLink.getGroupId());
                        mapPosition.put(flowExecutionQueryLink.getGroupId(), positionName);
                    }
                    continue;
                }
            }
            map.put("user", mapUser);
            map.put("org", mapOrg);
            map.put("role", mapRole);
            map.put("position", mapPosition);
            log.info("****{}*****", map);
            it.setOperationInfo(map);
        });
        return temp;
    }

    private static boolean isNumString(String str) {
        if (str.length() == 0 || str == null) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (!(ch >= '0' && ch <= '9')) {
                return false;
            }
        }
        return true;
    }

    public List<FlowTaskTrace> listByExample(FlowTaskTraceExample query) {
        return flowTaskTraceDAO.selectByExample(query);

    }

    public List<FlowTaskTrace> listByExample2(FlowTaskTraceExample query) {
        return flowTaskTraceDAO.selectByExample2(query);

    }

    @Override
    public List<FlowTaskTraceVo> listTaskTraces(TaskTraceQueryVo taskTraceQueryVo) {

        if (checkAuthorizeAndResolveTenant(taskTraceQueryVo)) {
            return Collections.emptyList();
        }

        // 任务列表
        List<String> taskIds = new ArrayList<>();

        // 先判断新增的工号字段填写了数值,则作为查询条件进行查询  只允许输入一个工号
        if (StringUtils.isNotBlank(taskTraceQueryVo.getEmployeeCode())) {
            List<String> employeeCodeList = new ArrayList<>();
            employeeCodeList.add(taskTraceQueryVo.getEmployeeCode());
            List<UserInfo> userInfos = null;
            try {
                // 批量查询用户信息
                userInfos = userService.getUserListByEmployeeCodeList(employeeCodeList);
            } catch (Exception ex) {
                logger.error("根据员工工号查询用户组件失败：" + ex.getMessage());
            }
            if (CollectionUtils.isNotEmpty(userInfos)) {
                String userId = userInfos.get(0).getUserCode();
                User user = userService.getFullUserInfo(userId);
                List<String> roleIds = new ArrayList<>();
                if (user.getRoleInfos() != null) {
                    user.getRoleInfos().forEach(it -> {
                        if (it == null) {
                            return;
                        }
                        roleIds.add(it.getRoleCode());
                    });
                }
                List<String> orgIds = new ArrayList<>();
                if (user.getOrgInfos() != null) {
                    user.getOrgInfos().forEach(it -> {
                        if (it == null) {
                            return;
                        }
                        orgIds.add(it.getOrgCode());
                    });
                }
                List<String> positionIds = new ArrayList<>();
                if (user.getPositionInfos() != null) {
                    user.getPositionInfos().forEach(it -> {
                        if (it == null) {
                            return;
                        }
                        positionIds.add(it.getPositionCode());
                    });
                }
                List<HttpFlowRecordsQueryVo> queryVos = flowTaskTraceDAO.getTasksByCandidateUser(userId, orgIds, roleIds, positionIds);
                queryVos.removeAll(Collections.singleton(null));
                if (CollectionUtils.isNotEmpty(queryVos)) {
                    for (HttpFlowRecordsQueryVo vo : queryVos) {
                        taskIds.add(vo.getTaskId());
                    }
                } else {
                    return null; //如果在act_ru_identityLink表中找不到待办信息 就直接返回空
                }
            } else {
                return null;   //如果根据工号找不到任何信息 就直接返回空
            }
        }

        PageHelper.startPage(taskTraceQueryVo.getPageNum(), taskTraceQueryVo.getPageSize());
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria();

        fillTenantQueryParams(taskTraceQueryVo, criteria);
        fillQueryConditions(taskTraceQueryVo, query, criteria);

        // 查询出来的任务列表如果不为空,则作为条件进行查询
        if (CollectionUtils.isNotEmpty(taskIds)) {
            criteria.andTaskIdIn(taskIds);
        }

        //return getPageableFlowTaskTraceVos(listByExample(query));
        return getPageableFlowTaskTraceVosForTaskList(listByExample2(query));
    }

    private void fillQueryConditions(TaskTraceQueryVo taskTraceQueryVo, FlowTaskTraceExample query, FlowTaskTraceExample.Criteria criteria) {
        //按照用户输入的角色id来筛选task
        if (StringUtils.isNotBlank(taskTraceQueryVo.getRoleIdStr())) {
            String[] tempRole = taskTraceQueryVo.getRoleIdStr().trim().split(",");
            if (tempRole.length > 0) {
                List<String> roleIds = Arrays.asList(tempRole);
                query.setRoleIds(roleIds);
            }
        }

        //按照用户输入的岗位id来筛选task
        if (StringUtils.isNotBlank(taskTraceQueryVo.getPositionStr())) {
            String[] tempPosition = taskTraceQueryVo.getPositionStr().trim().split(",");
            if (tempPosition.length > 0) {
                List<String> positionIds = Arrays.asList(tempPosition);
                query.setPositions(positionIds);
            }
        }

        //按照用户输入的组织id来筛选task
        if (StringUtils.isNotBlank(taskTraceQueryVo.getOrgStr())) {
            String[] tempOrg = taskTraceQueryVo.getOrgStr().trim().split(",");
            if (tempOrg.length > 0) {
                List<String> orgIds = Arrays.asList(tempOrg);
                query.setOrganizationIds(orgIds);
            }
        }

        if (StringUtils.isNotBlank(taskTraceQueryVo.getTaskName())) {
            criteria.andTaskNameLike("%" + taskTraceQueryVo.getTaskName() + "%");
        }
        //按照流程实例id进行筛选
        if (StringUtils.isNotBlank(taskTraceQueryVo.getProcessInstanceIdStr())) {
            String[] temp = taskTraceQueryVo.getProcessInstanceIdStr().trim().split(",");
            if (temp.length > 0) {
                List<String> processInstanceIds = Arrays.asList(temp);
                criteria.andProcessInstanceIdIn(processInstanceIds);
            }
        }
        //按照任务id进行筛选
        if (StringUtils.isNotBlank(taskTraceQueryVo.getTaskIdStr())) {
            String[] temp = taskTraceQueryVo.getTaskIdStr().trim().split(",");
            if (temp.length > 0) {
                List<String> taskId = Arrays.asList(temp);
                criteria.andTaskIdIn(taskId);
            }
        }
        if (CollectionUtils.isNotEmpty(taskTraceQueryVo.getApplyUserNames())) {
            criteria.andOperatorIn(taskTraceQueryVo.getApplyUserNames());
        }

        if (StringUtils.isNotBlank(taskTraceQueryVo.getStatus())) {
            criteria.andStatusEqualTo(taskTraceQueryVo.getStatus());
        }

        if (StringUtils.isNotBlank(taskTraceQueryVo.getLinkStatus())) {
            criteria.andLinkStatusEqualTo(taskTraceQueryVo.getLinkStatus());
        }

        if (StringUtils.isNotBlank(taskTraceQueryVo.getModelName())) {
            criteria.andModelNameLike("%" + taskTraceQueryVo.getModelName() + "%");
        }
    }

    @Override
    public List<FlowTaskTraceVo> queryTaskTraces(TaskTraceQueryVo taskTraceQueryVo) {
        if (checkAuthorizeAndResolveTenant(taskTraceQueryVo)) {
            return Collections.emptyList();
        }
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria();
        fillTenantQueryParams(taskTraceQueryVo, criteria);
        fillQueryConditions(taskTraceQueryVo, query, criteria);
        return convert(listByExample(query));
    }

    @Override
    public List<String> listUserNameByGroupIdAndType(String type, String groupId) {
        List<String> result = new ArrayList<>();
        List<User> users = new ArrayList<>();
        if ("role".equals(type)) {
            users = userRepository.listUserByRoleId(groupId);
        }
        if ("org".equals(type)) {
            users = userRepository.listUserByOrgCode(groupId);
        }
        if ("position".equals(type)) {
            users = userRepository.getUserListByPositionId(groupId);
        }
        if (CollectionUtils.isNotEmpty(users)) {
            users.forEach(it -> {
                if (it == null) {
                    return;
                }
                result.add(it.getUserName());
            });
        }
        return result;
    }

    @Override
    public List<FlowTaskTraceVo> listTaskTracesWithoutUserCheck(TaskTraceQueryVo taskTraceQueryVo) {
        FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
        List<String> processInstanceIdList = new ArrayList<>(taskTraceQueryVo.getProcessInstanceIds());

        flowTaskTraceExample.createCriteria()
                .andProcessInstanceIdIn(processInstanceIdList)
                .andLinkStatusEqualTo(taskTraceQueryVo.getLinkStatus());
        List<FlowTaskTrace> flowTaskTraceList = listByExample(flowTaskTraceExample);

        return convert(flowTaskTraceList);
    }

    @Override
    public List<FlowTaskTraceVo> listTaskTraces(HttpTaskQueryVo taskQueryVo) {
        PageHelper.startPage(taskQueryVo.getPageNum(), taskQueryVo.getPageSize());
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andLinkStatusEqualTo(taskQueryVo.getType());
        //
        if (Objects.nonNull(taskQueryVo.getAppId())) {
            criteria.andAppIdEqualTo(taskQueryVo.getAppId());
        }
        /*if (StringUtils.isNotBlank(taskQueryVo.getAssignee())) {
            criteria.andOperatorCodeEqualTo(taskQueryVo.getAssignee());
        }

        if (CollectionUtil.isNotEmpty(taskQueryVo.getAssignees())) {
            criteria.andOperatorCodeIn(taskQueryVo.getAssignees());
        }*/
        criteria.andStatusEqualTo(ProcessInstanceStatusEnum.NORMAL.getCode()); //只查询正常的
        Set<String> orgIdSet = this.selectOrgIdList(Long.parseLong(taskQueryVo.getAssignee()));
        String orderByClause = taskQueryVo.getOrderByClause();
        if (StringUtils.isNotEmpty(orderByClause) && StringUtils.isNotEmpty(orderByClause.trim())) {
            query.setOrderByClause(orderByClause);
        } else {
            query.setOrderByClause(" create_time desc");
        }
        query.setAssignee(taskQueryVo.getAssignee());
        query.setOrgIdSet(orgIdSet);
        List<String> processInstanceIds = taskQueryVo.getProcessInstanceIds();
        if (processInstanceIds != null && processInstanceIds.size() > 0) {
            criteria.andProcessInstanceIdIn(processInstanceIds);
        }
        logger.info("Assignee:" + taskQueryVo.getAssignee());
        logger.info("OrgIdSet:" + JSON.toJSONString(orgIdSet, SerializerFeature.PrettyFormat));
        return getPageableFlowTaskTraceVos(listByExample(query));
    }

    @Override
    public List<FlowTaskTraceVo> listTaskWithProcessVariable(HttpTaskQueryVo taskQueryVo) {
        PageHelper.startPage(taskQueryVo.getPageNum(), taskQueryVo.getPageSize());
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andLinkStatusEqualTo(taskQueryVo.getType());
        //
        if (Objects.nonNull(taskQueryVo.getAppId())) {
            criteria.andAppIdEqualTo(taskQueryVo.getAppId());
        }
//        criteria.andStatusEqualTo(ProcessInstanceStatusEnum.NORMAL.getCode()); //只查询正常的
        //2023-07-14 去除NORMAL限制，否则无法返回驳回、暂停等任务记录

        //增加时间筛选
        if (!Objects.isNull(taskQueryVo.getApproveTimeStart())) {
            criteria.andCreateTimeGreaterThanOrEqualTo(taskQueryVo.getApproveTimeStart());
        }
        if (!Objects.isNull(taskQueryVo.getApproveTimeEnd())) {
            criteria.andCreateTimeLessThanOrEqualTo(taskQueryVo.getApproveTimeEnd());
        }
        //Set<String> orgIdSet = this.selectOrgIdList(Long.parseLong(taskQueryVo.getAssignee()));
        String orderByClause = taskQueryVo.getOrderByClause();
        if (StringUtils.isNotEmpty(orderByClause) && StringUtils.isNotEmpty(orderByClause.trim())) {
            query.setOrderByClause(orderByClause);
        } else {
            query.setOrderByClause(" create_time desc");
        }
        query.setAssignee(taskQueryVo.getAssignee());
        query.setProcessCreateTimeStart(taskQueryVo.getProcessCreateTimeStart());
        query.setProcessCreateTimeEnd(taskQueryVo.getProcessCreateTimeEnd());
       //增加业务类型筛选
        if (!Objects.isNull(taskQueryVo.getBusiName())) {
            query.setBusiName(taskQueryVo.getBusiName());
        }
        // 如果状态时已完成状态时,需要单独的sql进行查询
        if (Objects.equals(taskQueryVo.getType(), TaskLinkStatusEnum.DONE.getCode())) {
            return getPageableFlowTaskTraceVos(this.getDoneTaskTrace(query));
        } else {
            //query.setOrgIdSet(orgIdSet);
            List<String> processInstanceIds = taskQueryVo.getProcessInstanceIds();
            if (processInstanceIds != null && processInstanceIds.size() > 0) {
                criteria.andProcessInstanceIdIn(processInstanceIds);
            }
            // 获取用户信息
            User userInfo = userService.getFullUserInfo(taskQueryVo.getAssignee());
            if (Objects.isNull(userInfo)) {
                logger.warn("无法查询到用户（id：{}）", taskQueryVo.getAssignee());
            } else {
                // 分别设置查询条件
                // 设置用户组织
                query.setCandidateUserOrg(this.resolveUserInfo(userInfo, "ORG"));
                // 设置用户角色
                query.setCandidateUserRole(this.resolveUserInfo(userInfo, "ROLE"));
                // 设置用户群组
                query.setCandidateUserGroup(this.resolveUserInfo(userInfo, "GROUP"));
                // 用户岗位
                query.setCandidateUserPosition(this.resolveUserInfo(userInfo, "POSITION"));
            }
            logger.info("Assignee:" + taskQueryVo.getAssignee());
            return getPageableFlowTaskTraceVos(listWithProcessVariableByExample(query));
        }
    }

    public List<FlowTaskTrace> listWithProcessVariableByExample(FlowTaskTraceExample query) {
        return flowTaskTraceDAO.selectProcessVariableByExample(query);
    }

    /**
     * 如果查询类型是已完成【DONE】的,则进行特殊的sql查询
     *
     * @param example
     * @return
     */
    public List<FlowTaskTrace> getDoneTaskTrace(FlowTaskTraceExample example) {
        return flowTaskTraceDAO.getDoneTaskTrace(example);
    }

    /**
     * 分别解析用户封装的信息
     *
     * @param userInfo
     * @param type
     * @return
     */
    @Override
    public String resolveUserInfo(User userInfo, String type) {
        Set<String> strList = new HashSet<>();
        if ("ORG".equals(type)) {
            // 用户组织信息
            List<OrgInfo> orgInfos = userInfo.getOrgInfos();
            if (CollectionUtils.isNotEmpty(orgInfos)) {
                for (OrgInfo orgInfo : orgInfos) {
                    strList.add(orgInfo.getOrgCode());
                }
            }
        } else if ("ROLE".equals(type)) {
            // 用户角色信息
            List<RoleInfo> roleInfos = userInfo.getRoleInfos();
            if (CollectionUtils.isNotEmpty(roleInfos)) {
                for (RoleInfo roleInfo : roleInfos) {
                    strList.add(roleInfo.getRoleCode());
                }
            }
        } else if ("GROUP".equals(type)) {
            // 用户组信息
            List<GroupInfo> groupInfos = userInfo.getGroupInfos();
            if (CollectionUtils.isNotEmpty(groupInfos)) {
                for (GroupInfo groupInfo : groupInfos) {
                    strList.add(groupInfo.getGroupCode());
                }
            }
        } else if ("POSITION".equals(type)) {
            // 用户岗位信息
            List<PositionInfo> positionInfos = userInfo.getPositionInfos();
            if (CollectionUtils.isNotEmpty(positionInfos)) {
                for (PositionInfo positionInfo : positionInfos) {
                    strList.add(positionInfo.getPositionCode());
                }
            }
        }

        return String.join(",", strList);
    }

    @Override
    public List<String> resolveUserInfoToList(User userInfo, String type) {
        List<String> strList = new ArrayList<>();
        if ("ORG".equals(type)) {
            // 用户组织信息
            List<OrgInfo> orgInfos = userInfo.getOrgInfos();
            if (CollectionUtils.isNotEmpty(orgInfos)) {
                for (OrgInfo orgInfo : orgInfos) {
                    strList.add(orgInfo.getOrgCode());
                }
            }
        } else if ("ROLE".equals(type)) {
            // 用户角色信息
            List<RoleInfo> roleInfos = userInfo.getRoleInfos();
            if (CollectionUtils.isNotEmpty(roleInfos)) {
                for (RoleInfo roleInfo : roleInfos) {
                    strList.add(roleInfo.getRoleCode());
                }
            }
        } else if ("GROUP".equals(type)) {
            // 用户组信息
            List<GroupInfo> groupInfos = userInfo.getGroupInfos();
            if (CollectionUtils.isNotEmpty(groupInfos)) {
                for (GroupInfo groupInfo : groupInfos) {
                    strList.add(groupInfo.getGroupCode());
                }
            }
        } else if ("POSITION".equals(type)) {
            // 用户岗位信息
            List<PositionInfo> positionInfos = userInfo.getPositionInfos();
            if (CollectionUtils.isNotEmpty(positionInfos)) {
                for (PositionInfo positionInfo : positionInfos) {
                    strList.add(positionInfo.getPositionCode());
                }
            }
        }
        return strList;
    }

    private Set<String> selectOrgIdList(Long userId) {
        Set<String> orgSet = new HashSet<>();
        SelectUserInfoReqVO selectUserInfoReqVO = new SelectUserInfoReqVO();
        selectUserInfoReqVO.setUserId(userId);
        BaseResult<RpcUserInfoVO> result = userFeignService.qryUserInfo(selectUserInfoReqVO);
        RpcUserInfoVO userInfoVo = result.getData();
        if (userInfoVo != null) {
            List<UserOrgResVO> orgVoList = userInfoVo.getOrgList();
            if (orgVoList != null) {
                for (UserOrgResVO orgVo : orgVoList) {
                    orgSet.add(orgVo.getOrgId() + "");
                }
            }
        }
        return orgSet;
    }

    @Override
    public List<FlowTaskTraceVo> listRunningTaskTraces(String processInstanceId) {
        TaskTraceQueryVo taskTraceQuery = new TaskTraceQueryVo();
        taskTraceQuery.setLinkStatus(TaskLinkStatusEnum.TODO.getCode());
        taskTraceQuery.setProcessInstanceIds(new HashSet<>(Arrays.asList(processInstanceId)));
        return listTaskTraces(taskTraceQuery);
    }

    @Override
    public List<FlowTaskTraceVo> listCompletedTaskTraces(String processInstanceId, String taskNodeCode) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId);
        if (StrUtil.isNotBlank(taskNodeCode)) {
            criteria.andActivityIdEqualTo(taskNodeCode);
        }
        //已完成
        criteria.andLinkStatusEqualTo(TaskLinkStatusEnum.DONE.getCode());
        query.setOrderByClause(" create_time ASC");
        return listByExample(query).stream().map(this::convert).collect(Collectors.toList());
    }

    private boolean checkAuthorizeAndResolveTenant(CataloguePageable cataloguePageable) {
        List<FlowTenantSimpleInfoVo> tenants = catalogueService.listCurrentUserTenants();
        if (CollectionUtils.isEmpty(tenants)) {
            logger.warn("当前用户没有权限访问任何租户数据");
            return true;
        }
        List<Integer> tenantIds = tenants.stream().map(FlowTenantSimpleInfoVo::getId).collect(Collectors.toList());
        resolveTenantId(cataloguePageable);
        if (Objects.nonNull(cataloguePageable.getTenantId())) {
            if (!tenantIds.contains(cataloguePageable.getTenantId())) {
                logger.warn("未授权的租户: {}", cataloguePageable.getTenantId());
                return true;
            }
        } else {
            cataloguePageable.setTenantIds(tenantIds);
        }
        return false;
    }

    @Override
    public FlowTaskTraceVo getTaskTraceByTaskId(String taskId) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        query.createCriteria().andTaskIdEqualTo(taskId);
        List<FlowTaskTrace> taskTraces = listByExample(query);
        if (CollectionUtils.isNotEmpty(taskTraces)) {
            return convert(taskTraces.get(0));
        }
        return null;
    }

    @Override
    public boolean updateTaskTraceById(FlowTaskTraceVo flowTaskTraceVo) {
        FlowTaskTrace entity = new FlowTaskTrace();
        BeanUtils.copyProperties(flowTaskTraceVo, entity);
        flowTaskTraceDAO.updateByPrimaryKeySelective(entity);
        return true;
    }

    @Override
    public void updateStatusToTimeout(String taskId) {
        FlowTaskTraceVo entity = getTaskTraceByTaskId(taskId);
        if (Objects.isNull(entity)) {
            return;
        }
        if (!Objects.equals(entity.getStatus(), ProcessInstanceStatusEnum.PAUSE.getCode())) {
            entity.setStatus(ProcessInstanceStatusEnum.TIMEOUT.getCode());
        }
        entity.setFlag(2);
        entity.setUpdateTime(new Date());
        flowTaskTraceDAO.updateByPrimaryKeySelective(convert(entity));
    }

    @Override
    public void updateStatusToWarning(String taskId) {
        FlowTaskTraceVo entity = getTaskTraceByTaskId(taskId);
        if (Objects.isNull(entity)) {
            return;
        }
        if (!Objects.equals(entity.getStatus(), ProcessInstanceStatusEnum.PAUSE.getCode())) {
            entity.setStatus(ProcessInstanceStatusEnum.WARNING.getCode());
        }
        entity.setFlag(1);
        entity.setUpdateTime(new Date());
        flowTaskTraceDAO.updateByPrimaryKeySelective(convert(entity));
    }

    @Override
    public void updateRunningTaskStatusAfterProcessInstanceCancel(String processInstanceId) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId).andLinkStatusEqualTo(TaskLinkStatusEnum.TODO.getCode());
        FlowTaskTrace entity = new FlowTaskTrace();
        entity.setStatus(ProcessInstanceStatusEnum.END.getCode());
        entity.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
        flowTaskTraceDAO.updateByExampleSelective(entity, query);
    }

    @Override
    public void updateStatusAndOperator(String taskId, String userId, String operator) {
        FlowTaskTraceVo entity = getTaskTraceByTaskId(taskId);
        if (Objects.isNull(entity)) {
            return;
        }
        entity.setCompleteTime(new Date());
        entity.setStatus(ProcessInstanceStatusEnum.REJECT.getCode());
        entity.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
        entity.setFlag(0);
        entity.setUpdateTime(new Date());
        entity.setOperatorCode(userId);
        entity.setOperator(operator);
        flowTaskTraceDAO.updateByPrimaryKeySelective(convert(entity));
    }

    @Override
    public void updateStatusToReject(String taskId) {
        FlowTaskTraceVo entity = getTaskTraceByTaskId(taskId);
        if (Objects.isNull(entity)) {
            return;
        }
        entity.setCompleteTime(new Date());
        entity.setStatus(ProcessInstanceStatusEnum.REJECT.getCode());
//        entity.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
        entity.setFlag(0);
        entity.setUpdateTime(new Date());
        flowTaskTraceDAO.updateByPrimaryKeySelective(convert(entity));
    }

    @Override
    public void deleteByPrimaryKey(String id) {
        flowTaskTraceDAO.deleteByPrimaryKey(id);
    }

    private void resolveTenantId(CataloguePageable cataloguePageable) {
        if (Objects.nonNull(cataloguePageable.getTenantId())) {
            return;
        }
        if (Objects.nonNull(cataloguePageable.getAppId())) {
            Integer tenantId = resolveTenantIdByAppId(cataloguePageable.getAppId());
            if (Objects.nonNull(tenantId)) {
                cataloguePageable.setTenantId(tenantId);
            }
        }
    }

    private Integer resolveTenantIdByAppId(Integer appId) {
        FlowApp detail = flowAppRepository.detail(appId);
        if (Objects.nonNull(detail)) {
            return detail.getTenantId();
        }
        return null;
    }

    private FlowTaskTraceVo convert(FlowTaskTrace entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        FlowTaskTraceVo result = new FlowTaskTraceVo();
        BeanCopierUtils.copyProperties(entity, result);
        return result;
    }

    private FlowTaskTrace convert(FlowTaskTraceVo vo) {
        if (Objects.isNull(vo)) {
            return null;
        }
        FlowTaskTrace result = new FlowTaskTrace();
        BeanCopierUtils.copyProperties(vo, result);
        return result;
    }

    private List<FlowTaskTraceVo> convert(List<FlowTaskTrace> sources) {
        return sources.stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public int updateAssignInfoByTaskId(FlowTaskTraceVo flowTaskTraceVo) {
        FlowTaskTrace entity = new FlowTaskTrace();
        BeanUtils.copyProperties(flowTaskTraceVo, entity);
        int i = flowTaskTraceDAO.updateAssignInfoByTaskId(entity);
        return i;
    }

    @Override
    public FlowTaskTraceVo getFlowTaskByTaskIdAndUser(TaskCandidateQueryVo taskCandidateQueryVo) {

        List<FlowTaskTrace> flowTaskTraceList = flowTaskTraceDAO.getFlowTaskTraceByTaskIdAndUser(taskCandidateQueryVo);
        if (Objects.nonNull(flowTaskTraceList) && !flowTaskTraceList.isEmpty()) {
            FlowTaskTraceVo flowTaskTraceVo = new FlowTaskTraceVo();
            BeanCopierUtils.copyProperties(flowTaskTraceList.get(0), flowTaskTraceVo);
            return flowTaskTraceVo;
        }
        return null;
    }

    @Override
    public List<FlowTaskTraceVo> getFlowTaskByModelAndUser(TaskCandidateQueryVo taskCandidateQueryVo) {

        List<FlowTaskTrace> flowTaskTraceList = flowTaskTraceDAO.getFlowTaskByModelAndUser(taskCandidateQueryVo);

        return convert(flowTaskTraceList);
    }

    @Override
    public List<FlowTaskTraceVo> getFlowTaskTracesByProInsIdAndNode(String processInstanceId, String taskNodeCode) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId);
        if (StrUtil.isNotBlank(taskNodeCode)) {
            criteria.andActivityIdEqualTo(taskNodeCode);
        }
        query.setOrderByClause(" create_time ASC");
        return listByExample(query).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<FlowTaskTraceVo> getFlowTaskTracesByProInsIdAndNode2(String processInstanceId, String taskNodeCode, String orderBy, String orderRule) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId);
        if (StrUtil.isNotBlank(taskNodeCode)) {
            criteria.andActivityIdEqualTo(taskNodeCode);
        }
        query.setOrderByClause(" " + orderBy + " " + orderRule + "");
        return listByExample(query).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<FlowTaskTraceVo> getFlowTaskTracesByProInsIdAndLinkStatus(String processInstanceId, String LinkStatus) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria().andProcessInstanceIdEqualTo(processInstanceId);
        if (StrUtil.isNotBlank(LinkStatus)) {
            criteria.andLinkStatusEqualTo(LinkStatus);
        }
        query.setOrderByClause(" create_time ASC");
        return listByExample(query).stream().map(this::convert).collect(Collectors.toList());
    }

    /**
     * 批量查询流程节点的审批记录
     *
     * @param httpFlowRecordsQueryDto
     * @return
     */
    @Override
    public List<HttpFlowRecordsQueryVo> batchQueryFlowRecords(HttpFlowRecordsQueryDto httpFlowRecordsQueryDto) {
        return flowTaskTraceDAO.getFlowRecordsByTaskIdAndProcessId(httpFlowRecordsQueryDto);
    }

    @Override
    public List<HttpFlowNodeRecordsQueryVo> getTaskCodeList(HttpGetTaskDto httpGetTaskDto) {
        return flowTaskTraceDAO.getFlowRecordsByModelKey(httpGetTaskDto);
    }

    /**
     * 根据流程id，查询每个节点最近的审批信息（驳回多次，只取最新一次审批结果）
     *
     * @param processInstanceId 流程实例id
     */

    @Override
    public List<FlowTaskTraceVo> getAllLastTaskRecords(String processInstanceId) {
        List<FlowTaskTrace> taskTraces = flowTaskTraceDAO.getAllLastTaskRecords(processInstanceId);
        if (CollectionUtils.isNotEmpty(taskTraces)) {
            return convert(taskTraces);
        }
        return null;
    }

    @Override
    public List<FlowTaskTraceVo> getTaskTraceByParentId(String parentId) {
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        query.createCriteria().andParentIdEqualTo(parentId);
        List<FlowTaskTrace> taskTraces = listByExample(query);
        if (CollectionUtils.isNotEmpty(taskTraces)) {
            return convert(taskTraces);
        }
        return null;
    }

    /**
     * 条件查询列表
     *
     * @param taskStatisticsQueryVo 查询条件
     * @return 列表数据
     */

    @Override
    public List<FlowTaskTraceVo> listTaskWithOutPage(TaskStatisticsQueryVo taskStatisticsQueryVo) {
        List<FlowTaskTrace> flowTaskTraces = listTaskByExample(taskStatisticsQueryVo);
        return convert(flowTaskTraces);
    }

    private List<FlowTaskTrace> listTaskByExample(TaskStatisticsQueryVo taskStatisticsQueryVo) {
        if (checkAuthorizeAndResolveTenant(taskStatisticsQueryVo)) {
            return Collections.emptyList();
        }
        FlowTaskTraceExample query = new FlowTaskTraceExample();
        FlowTaskTraceExample.Criteria criteria = query.createCriteria();
        query.setOrderByClause(" create_time desc");


        fillTenantQueryParams(taskStatisticsQueryVo, criteria);

        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getModelKey())) {
            criteria.andModelKeyLike("%" + taskStatisticsQueryVo.getModelKey() + "%");
        }

        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getModelName())) {
            criteria.andModelNameLike("%" + taskStatisticsQueryVo.getModelName() + "%");
        }


        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getActivityId())) {
            criteria.andActivityIdLike("%" + taskStatisticsQueryVo.getActivityId() + "%");
        }


        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getTaskName())) {
            criteria.andTaskNameLike("%" + taskStatisticsQueryVo.getTaskName() + "%");
        }

        if (Objects.nonNull(taskStatisticsQueryVo.getStartTime()) && Objects.nonNull(taskStatisticsQueryVo.getEndTime())) {
            criteria.andCreateTimeBetween(taskStatisticsQueryVo.getStartTime(), taskStatisticsQueryVo.getEndTime());
        }

        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getStatus())) {
            criteria.andStatusEqualTo(taskStatisticsQueryVo.getStatus());
        }

        if (CollectionUtils.isNotEmpty(taskStatisticsQueryVo.getProcessInstanceIds())) {
            criteria.andProcessInstanceIdIn(taskStatisticsQueryVo.getProcessInstanceIds());
        }

        if (StringUtils.isNotBlank(taskStatisticsQueryVo.getLinkStatus())) {
            criteria.andLinkStatusEqualTo(taskStatisticsQueryVo.getLinkStatus());
        }

        List<FlowTaskTrace> flowTaskTraces = listByExample(query);
        return flowTaskTraces;
    }

}
